package com.superquan.selfstudybootmybatis.utils.httpapply;

import com.alibaba.fastjson.JSONObject;
import com.superquan.selfstudybootmybatis.entity.Uce56Result;
import com.superquan.selfstudybootmybatis.utils.JsonUtil;
import com.superquan.selfstudybootmybatis.utils.encrypt.md5.MD5;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author zwq
 * @description 请求第三方接口
 * @date 2022/8/30
 */
@Slf4j
public class HttpClientUtil {

    private static PoolingHttpClientConnectionManager pool = new PoolingHttpClientConnectionManager();

    /**
     * 请求第三方溯源接口
     * @param url
     * @param param
     * @return
     */
    public static Uce56Result doPostForTrace(String url, Object param) {

        PostMethod post = new PostMethod(url);
        try {
            post.setRequestEntity(new StringRequestEntity(JsonUtil.toJSONString(param),"application/json","UTF-8"));
            String timestamp = System.currentTimeMillis() + "";
            String clientId="TRACE";
            String secretKey = "WfTraceVxzPtl";
            String token = MD5.getMD5(  clientId + timestamp + secretKey);
            post.setRequestHeader("clientId", clientId);
            post.setRequestHeader("timestamp", timestamp);
            post.setRequestHeader("token", token);
            HttpClient client = new HttpClient();
            client.executeMethod(post);
            byte[] responseBody = post.getResponseBody();
            String body = new String(responseBody, StandardCharsets.UTF_8);
            return JsonUtil.parseJSONObject(body,Uce56Result.class);
        } catch (Exception ex) {
            Uce56Result uce56Result = new Uce56Result();
            uce56Result.setCode("-999");
            uce56Result.setMsg("接口请求异常！");
            return uce56Result;
        }
    }

    /**
     * post请求调用第三方商派接口  参数拼接到URL上面
     * 如：https://apigateway.shopex.cn/router?method=shopex.queue.read&app_key=xxx&client_secret=xxxxx&topic=xxxx&drop=false&num=1
     * @param url
     * @param param
     * @return
     */
    public static String doPostForTrader(String url, Map<String, String> param) {
        CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(pool).build();
        // 创建Httpclient对象
        CloseableHttpResponse response = null;
        String resultString = "";
        try {
            // 创建Http Post请求
            HttpPost httpPost = new HttpPost(url);
            // 创建参数列表
            if (param != null) {
                List<NameValuePair> paramList = new ArrayList<>();
                for (String key : param.keySet()) {
                    paramList.add(new BasicNameValuePair(key, param.get(key)));
                }
                // 模拟表单
                UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList, "utf-8");
                httpPost.setEntity(entity);
            }
            // 执行http请求
            response = httpclient.execute(httpPost);
            if(HttpStatus.SC_OK != response.getStatusLine().getStatusCode()){
                log.error("请求第三方商派失败:{}", response.getStatusLine().getStatusCode());
            }
            resultString = EntityUtils.toString(response.getEntity(), "utf-8");
        } catch (Exception e) {
            log.error("请求httpClient异常"+e.getMessage());
            e.printStackTrace();
        } finally {
            try {
                response.close();
            } catch (IOException e) {
                log.error("关闭httpClient异常"+e.getMessage());
                e.printStackTrace();
            }
        }
        return resultString;
    }

    /**
     * localhost：8091/message
     *
     * @param url    http:localhost：8080
     * @return params 参数 放在响应头中
     * @throws ClientProtocolException
     * @throws IOException
     */
    public static JSONObject doPost(String url, String params) throws Exception {
        org.apache.http.client.HttpClient httpClient = new DefaultHttpClient();
        HttpPost httpPost = new HttpPost(url);
        httpPost.setHeader("Content-Type", "application/json;charset=UTF-8");
        if (StringUtils.isNotBlank(params)) {
            httpPost.setEntity(new StringEntity(params, "utf-8"));
        }
        HttpResponse httpResponse = httpClient.execute(httpPost);
        // 请求和响应都成功了
        HttpEntity entity = httpResponse.getEntity();// 调用getEntity()方法获取到一个HttpEntity实例
        String response  = EntityUtils.toString(entity, "utf-8");// 用EntityUtils.toString()这个静态方法将HttpEntity转换成字符串,防止
        JSONObject jsonObject =JSONObject.parseObject(response);
        return jsonObject;
    }


    /**
     * 以GET方式请求第三方接口
     * @param url
     * @param param
     * @return
     */
    public static String doGet(String url, Map<String, String> param) {
        CloseableHttpClient httpclient = HttpClients.custom().setConnectionManager(pool).build();
        // 创建Httpclient对象
        String resultString = "";
        CloseableHttpResponse response = null;
        try {
            // 创建uri
            URIBuilder builder = new URIBuilder(url);
            buildGetParam(param, builder);
            // 执行请求
            response = httpclient.execute(new HttpGet(builder.build()));
            log.info("请求httpClient返回结果"+response);
            if (response.getStatusLine().getStatusCode() == 200) {
                //进行unicode解码
                resultString = decodeUnicode(EntityUtils.toString(response.getEntity(), "UTF-8"));
                //去除转义符 "\"
                resultString = StringEscapeUtils.unescapeJava(resultString);
            }
        } catch (Exception e) {
            log.error("请求httpClient异常"+e.getMessage());
            e.printStackTrace();
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
                httpclient.close();
            } catch (IOException e) {
                log.error("关闭httpClient异常"+e.getMessage());
                e.printStackTrace();
            }
        }
        return resultString;
    }

    /**
     * 构建参数
     * @param param
     * @param builder
     */
    public static void buildGetParam(Map<String, String> param, URIBuilder builder) {
        if (param != null) {
            for (String key : param.keySet()) {
                builder.addParameter(key, param.get(key));
            }
        }
    }


    /**
     * unicode 转换成 中文
     *
     * @author fanhui 2007-3-15
     * @param theString
     * @return
     */
    public static String decodeUnicode(String theString) {
        char aChar;
        int len = theString.length();
        StringBuffer outBuffer = new StringBuffer(len);
        for (int x = 0; x < len;) {
            aChar = theString.charAt(x++);
            if (aChar == '\\') {
                aChar = theString.charAt(x++);
                if (aChar == 'u') {
                    int value = 0;
                    for (int i = 0; i < 4; i++) {
                        aChar = theString.charAt(x++);
                        switch (aChar) {
                            case '0':
                            case '1':
                            case '2':
                            case '3':
                            case '4':
                            case '5':
                            case '6':
                            case '7':
                            case '8':
                            case '9':
                                value = (value << 4) + aChar - '0';
                                break;
                            case 'a':
                            case 'b':
                            case 'c':
                            case 'd':
                            case 'e':
                            case 'f':
                                value = (value << 4) + 10 + aChar - 'a';
                                break;
                            case 'A':
                            case 'B':
                            case 'C':
                            case 'D':
                            case 'E':
                            case 'F':
                                value = (value << 4) + 10 + aChar - 'A';
                                break;
                            default:
                                throw new IllegalArgumentException(
                                        "Malformed      encoding.");
                        }
                    }
                    outBuffer.append((char) value);
                } else {
                    if (aChar == 't') {
                        aChar = '\t';
                    } else if (aChar == 'r') {
                        aChar = '\r';
                    } else if (aChar == 'n') {
                        aChar = '\n';
                    } else if (aChar == 'f') {
                        aChar = '\f';
                    }
                    outBuffer.append(aChar);
                }
            } else {
                outBuffer.append(aChar);
            }
        }
        return outBuffer.toString();
    }
}
